library ieee;
 use ieee.std_logic_1164.all;
 use ieee.std_logic_unsigned.all;


library work;
 use work.router_pack.all;

-------------------------------------------------------------------------------
entity vc_arbiter is
-------------------------------------------------------------------------------
port( 
      -- General Control: --
      RESET     : in  std_logic;  -- Active Low 

      -- VCs Interface: --
      R_ARR     : in  std_logic_vector(num_of_vc_con-1 downto 0); -- requests from different VCs.
      A_ARR     : out std_logic_vector(num_of_vc_con-1 downto 0); -- requests from different VCs.
      DI        : in  data_mvc_bus_type;                          -- array of VC busses.

      -- SPA Interface: --
      RO        : out std_logic;
      AO        : in  std_logic;
      DO        : out std_logic_vector(vc_width+flit_width_con-1 downto 0)
);           
-------------------------------------------------------------------------------
end vc_arbiter ;
-------------------------------------------------------------------------------

-------------------------------------------------------------------------------
architecture vc_arbiter_arch of vc_arbiter is
-------------------------------------------------------------------------------

component c_element
port( 
      -- Input i/f: --
      A     : in  std_logic;
      B     : in  std_logic;

      -- output i/f: --
      Q     : out std_logic
);           
end component;

component mutex
port( 
      -- MUTEX input i/f: --
      R1      : in  std_logic;
      R2      : in  std_logic;

      -- MUTEX output i/f: --
      G1      : out std_logic;
      G2      : out std_logic
);           
end component;

-- NOR (small)
COMPONENT nr02d1 -- drive x1
PORT(
  a1 : IN std_logic; 
  a2 : IN std_logic;
  zn : OUT std_logic
);
END COMPONENT;

signal ce_out : std_logic_vector(num_of_vc_con-1 downto 0);
signal g_arr  : std_logic_vector(num_of_vc_con-1 downto 0);
signal grant_not : std_logic;

begin

-- 1. VC arbitration: --
-- MUTEX: --
u_mutex_vc: mutex
port map( 
      R1      => R_ARR(0),
      R2      => R_ARR(1),

      G1      => g_arr(0),
      G2      => g_arr(1)
);

-- 2. C-elements: --
c_elements_gen: for i in 0 to (num_of_vc_con-1) generate

 u_c_element1: c_element
 port map( 
      A     => g_arr(i),
      B     => grant_not,

      Q     => ce_out(i)
 ); 
 
 -- 2.1. Acknowelege to the VCs: --
 A_ARR(i) <= AO when (ce_out(i)='1') else '0';
 
end generate;

-- 3. RO out: --
RO <= ce_out(0) or ce_out(1);

-- 4. Data Muxing: --
-- VC Mux: --
vc_out_mux_proc: process(ce_out, DI)
begin
 case ce_out is
  when "01" =>
   DO <= '0' & DI(0); -- additional bit for the VC indication
  when "10" =>
   DO <= '1' & DI(1);
  when others =>
   DO <= '0' & DI(0);
 end case;
end process;

-- 5. Reversing the AO + Reset: --
u_ao_not: nr02d1
port map(
      a1 => RESET,
      a2 => AO,
      zn => grant_not
);

-------------------------------------------------------------------------------
end vc_arbiter_arch;
-------------------------------------------------------------------------------                 

   
-------------------------------------------------------------------------------
configuration  vc_arbiter_cfg  of vc_arbiter is
-------------------------------------------------------------------------------
   for vc_arbiter_arch
   end for;
-------------------------------------------------------------------------------
end  vc_arbiter_cfg;              
-------------------------------------------------------------------------------
                 
